定期ミートアップ 第62回
milika
async ifを実装した
code:txt
extern print(Int n) -> Null
extern(async) sleep_sec(Int n) -> Null
fun chiika_main() -> Null {
print(
if (true) {
sleep_sec(1)
yield 456
} else {
yield 789
}
)
return null
}
yieldは、MLIRのscf.yieldに対応
lower_async_if.rs
ifを、「trueのときの関数」「falseのときの関数」「ifよりあとの関数」に分割
code:txt
fun chiika_main?() -> Null { cond_return true, chiika_main't?(...), chiika_main'f?(...) #-> Void }
fun chiika_main't?() -> Null { return chiika_main'e?(456) # Null #-> Void }
fun chiika_main'f?() -> Null { return chiika_main'e?(789) # Null #-> Void }
fun chiika_main'e?(Int $ifResult) -> Null { return null # Null #-> Void }
asyncness_check.rs
各関数のsync(下記の[+]マーク)とasync([*])を判定
判定はconservative
code:txt
fun chiika_main*() -> Null { cond_return true, chiika_main't*(...), chiika_main'f+(...) #-> Void }
fun chiika_main't*() -> Null { return chiika_main'e+(456) # Null #-> Void }
fun chiika_main'f+() -> Null { return chiika_main'e+(789) # Null #-> Void }
fun chiika_main'e+(Int $ifResult) -> Null { return null # Null #-> Void }
async_splitter.rs
asyncな関数を、async callを境に分割
あと、cond_return命令をif式に戻しつつ、必要に応じてtrue関数・false関数の呼び出しをcps対応
code:txt
fun chiika_main.(ChiikaEnv $env, (ChiikaEnv,Null)->RustFuture $cont) -> RustFuture { return if(true){
yield chiika_main't.(%arg_0, %arg_1) # RustFuture } else {
yield %arg_1.(%arg_0, chiika_main'f+()) # RustFuture }
fun chiika_main't.(ChiikaEnv $env, (ChiikaEnv,Null)->RustFuture $cont) -> RustFuture { chiika_env_push.(%arg_0, FunToAny(%arg_1)) #-> Int return sleep_sec.(%arg_0, chiika_main't_1, 1) # RustFuture #-> Void }
fun chiika_main't_1.(ChiikaEnv $env, Null $async_result) -> RustFuture { return AnyToFun((ChiikaEnv,Null)->RustFuture)(chiika_env_pop.(%arg_0, 1)).(%arg_0, chiika_main'e+(456)) # RustFuture #-> Void }
fun chiika_main'f.() -> Null { return chiika_main'e+(789) # Null #-> Void }
fun chiika_main'e.(Int $ifResult) -> Null { return null # Null #-> Void }
lower_if.rs
if式をcf.cond_brに変換
scf.ifはfunc.returnを内包できないため`
code:txt
fun chiika_main(ChiikaEnv $env, (ChiikaEnv,Null)->RustFuture $cont) -> RustFuture {
%cond_br true ^bb1 ^bb2; #-> Void ^bb1()
%br ^bb3(chiika_main't.(%arg_0, %arg_1)) # RustFuture; #-> Void ^bb2()
%br ^bb3(%arg_1.(%arg_0, chiika_main'f+())) # RustFuture; #-> Void ^bb3(RustFuture)
return %block_arg # RustFuture; #-> Void }
...
async whileを実装したい
自己再帰にloweringすることを考えている
→自己再帰で無限ループできる(stack overflowしない)ことが必要
.llがtail callになっていればよさそう?